import MysApi from './MysApi.js'
import Storage from './Storage.js'
import Config from './Config.js'

/**
 * 签到服务类
 */
export default class SignService {
  constructor() {
    this.storage = Storage
    this.config = Config
  }

  /**
   * 执行签到
   */
  async sign(qq, uid, cookie, game = 'gs') {
    try {
      const api = new MysApi(uid, cookie, { game })
      
      // 获取签到信息
      const signInfo = await api.getSignInfo()
      
      // 检查返回码
      if (signInfo.retcode !== 0) {
        return this.handleError(signInfo.retcode, signInfo.message)
      }

      const data = signInfo.data
      
      // 2. 检查是否已签到
      if (data.is_sign) {
        const dayOfMonth = parseInt(data.today.split('-')[2])
        const signedCount = data.total_sign_day
        const missedDays = dayOfMonth - signedCount
        
        logger.info(`[签到插件] UID:${uid} 今日已签到`)
        
        // 获取今日奖励信息（已签到的那天）
        let reward = null
        try {
          const rewardsData = await api.getSignRewards()
          if (rewardsData.retcode === 0 && rewardsData.data?.awards) {
            // 今天已经签到了，获取今天的奖励（索引 = 签到天数 - 1）
            const todayIndex = signedCount - 1
            reward = rewardsData.data.awards[todayIndex]
          }
        } catch (error) {
          logger.warn(`[签到插件] 获取奖励信息失败: ${error.message}`)
        }
        
        const result = {
          success: true,
          alreadySigned: true,
          message: `今日已签到！本月漏签次数：${missedDays}`,
          reward: reward ? {
            name: reward.name,
            count: reward.cnt,
            icon: reward.icon
          } : null,
          data: {
            totalSignDay: signedCount,
            missedDays
          }
        }
        
        this.storage.addSignLog(qq, game, uid, result)
        return result
      }

      // 3. 执行签到
      const signResult = await api.doSign()
      
      if (signResult.retcode !== 0) {
        return this.handleError(signResult.retcode, signResult.message)
      }

      // 4. 获取签到奖励信息
      const rewardsData = await api.getSignRewards()
      let reward = null
      
      if (rewardsData.retcode === 0 && rewardsData.data?.awards) {
        // 今天是第几天（从0开始）
        const todayIndex = data.total_sign_day
        reward = rewardsData.data.awards[todayIndex]
      }

      // 5. 再次获取签到信息确认
      const newSignInfo = await api.getSignInfo()
      const newData = newSignInfo.data || data
      
      const dayOfMonth = parseInt(newData.today.split('-')[2])
      const signedCount = newData.total_sign_day
      const missedDays = dayOfMonth - signedCount

      const result = {
        success: true,
        alreadySigned: false,
        message: '签到成功',
        reward: reward ? {
          name: reward.name,
          count: reward.cnt,
          icon: reward.icon
        } : null,
        data: {
          totalSignDay: signedCount,
          missedDays
        }
      }

      logger.info(`[签到插件] UID:${uid} 签到成功, 获得: ${reward?.name} x${reward?.cnt}`)
      this.storage.addSignLog(qq, game, uid, result)
      
      return result

    } catch (error) {
      logger.error(`[签到插件] 签到异常:`, error)
      return {
        success: false,
        message: `签到失败: ${error.message}`
      }
    }
  }

  /**
   * 处理错误码
   */
  handleError(retcode, message) {
    const errorMap = {
      '-5003': '今日已签到',
      '-10001': 'Cookie已失效，请重新绑定',
      '-100': 'Cookie已失效，请重新绑定',
      '10001': '请先登录',
      '1008': '请先在米游社绑定角色',
      '10102': '米游社数据未公开',
      '-1': '网络请求失败',
      '1034': '遇到验证码，请稍后再试',
      '-10002': 'Cookie格式不完整，需要包含ltoken字段',
      '2001': '活动已结束或Cookie不完整'
    }

    const errorMsg = errorMap[String(retcode)] || message || '未知错误'
    
    
    return {
      success: false,
      retcode,
      message: errorMsg
    }
  }

  /**
   * 批量签到
   */
  async signAll(qq, game = 'gs') {
    const user = this.storage.getUser(qq)
    
    if (!user || !user.cookie || !user.uid) {
      return {
        success: false,
        message: '请先绑定Cookie'
      }
    }

    const result = await this.sign(qq, user.uid, user.cookie, game)
    return result
  }

  /**
   * 获取签到状态
   */
  async getSignStatus(qq, uid, cookie, game = 'gs') {
    try {
      const api = new MysApi(uid, cookie, { game })
      const signInfo = await api.getSignInfo()
      
      if (signInfo.retcode !== 0) {
        return this.handleError(signInfo.retcode, signInfo.message)
      }

      const data = signInfo.data
      const dayOfMonth = parseInt(data.today.split('-')[2])
      const missedDays = dayOfMonth - data.total_sign_day

      // 获取奖励信息
      let reward = null
      try {
        const rewardsData = await api.getSignRewards()
        if (rewardsData.retcode === 0 && rewardsData.data?.awards) {
          // 如果已签到，获取今天的奖励（索引 = 签到天数 - 1）
          // 如果未签到，获取今天要签到的奖励（索引 = 签到天数）
          const todayIndex = data.is_sign ? data.total_sign_day - 1 : data.total_sign_day
          const rewardData = rewardsData.data.awards[todayIndex]
          if (rewardData) {
            reward = {
              name: rewardData.name,
              count: rewardData.cnt,
              icon: rewardData.icon
            }
          }
        }
      } catch (error) {
        logger.warn(`[签到插件] 获取奖励信息失败: ${error.message}`)
      }

      return {
        success: true,
        data: {
          isSigned: data.is_sign,
          totalSignDay: data.total_sign_day,
          missedDays,
          today: data.today,
          monthFirst: data.month_first || data.is_sign,
          reward
        }
      }
    } catch (error) {
      logger.error(`[签到插件] 获取签到状态失败:`, error)
      return {
        success: false,
        message: `获取状态失败: ${error.message}`
      }
    }
  }

  /**
   * 按游戏类型执行自动签到任务
   * @param {string} game - 游戏类型 'gs' 或 'sr'
   */
  async autoSignTaskByGame(game = 'gs') {
    const gameName = game === 'gs' ? '原神' : '星铁'
    logger.info(`[签到插件] 开始执行${gameName}自动签到任务`)
    
    // 获取该游戏的自动签到用户
    const users = this.storage.getAutoSignUsers(game)
    
    if (users.length === 0) {
      logger.info(`[签到插件] 没有需要${gameName}自动签到的用户`)
      return {
        total: 0,
        success: 0,
        failed: 0,
        results: [],
        game,
        gameName
      }
    }

    logger.info(`[签到插件] 共 ${users.length} 个${gameName}签到任务`)

    const results = []
    let successCount = 0
    let failedCount = 0

    for (const user of users) {
      try {
        // 添加延迟，避免请求过快
        const interval = Config.get('autoSign.interval', 3) * 1000
        const randomDelay = Config.get('autoSign.randomDelay', 2) * 1000
        await this.sleep(interval + Math.random() * randomDelay)
        
        // 获取对应游戏的UID
        let uid = null
        
        // 从 user.uid 对象中提取对应游戏的 UID
        if (typeof user.uid === 'object' && user.uid !== null) {
          // 新版数据格式：{ gs: 'xxx', sr: 'xxx' }
          uid = user.uid[game]
        } else if (typeof user.uid === 'string') {
          // 旧版数据格式：字符串（默认为原神）
          uid = game === 'gs' ? user.uid : null
        }
        
        // 如果没有 UID，尝试从 UserManager 获取
        if (!uid) {
          const UserManagerClass = (await import('./UserManager.js')).default
          const userManager = new UserManagerClass()
          
          // 先尝试从本地获取
          uid = await userManager.getGameUid(user.qq, game)
          if (uid) {
            logger.info(`[签到插件] 从本地获取${game === 'gs' ? '原神' : '星铁'}UID: ${uid}`)
          } else {
            // 本地没有，从API获取
            logger.info(`[签到插件] 本地未找到${game === 'gs' ? '原神' : '星铁'}UID，尝试从API获取`)
            uid = await userManager.getGameUidFromApi(user.qq, user.cookie, game)
            if (uid) {
              logger.info(`[签到插件] 从API获取到${game === 'gs' ? '原神' : '星铁'}UID: ${uid}`)
            }
          }
        }
        
        if (!uid) {
          logger.warn(`[签到插件] QQ:${user.qq} ${gameName} 未找到UID，跳过`)
          failedCount++
          results.push({
            qq: user.qq,
            game,
            gameName,
            result: { success: false, message: '未找到UID' }
          })
          continue
        }
        
        logger.info(`[签到插件] 正在为 QQ:${user.qq} UID:${uid} 执行${gameName}签到`)
        const result = await this.sign(user.qq, uid, user.cookie, game)
        
        if (result.success) {
          successCount++
        } else {
          failedCount++
        }

        results.push({
          qq: user.qq,
          uid: uid,
          game,
          gameName,
          result
        })

      } catch (error) {
        logger.error(`[签到插件] QQ:${user.qq} ${gameName} 自动签到异常:`, error)
        failedCount++
        
        // 获取错误时的 UID（如果有）
        let errorUid = null
        if (typeof user.uid === 'object' && user.uid !== null) {
          errorUid = user.uid[game]
        } else if (typeof user.uid === 'string' && game === 'gs') {
          errorUid = user.uid
        }
        
        results.push({
          qq: user.qq,
          game,
          gameName,
          uid: errorUid,
          result: {
            success: false,
            message: error.message
          }
        })
      }
    }

    logger.info(`[签到插件] ${gameName}自动签到任务完成: 成功${successCount}个, 失败${failedCount}个`)
    
    // 记录失败详情
    if (failedCount > 0) {
      const failedResults = results.filter(r => !r.result.success)
      failedResults.forEach(r => {
        const uidText = r.uid ? `UID:${r.uid}` : ''
        logger.warn(`[签到插件] QQ:${r.qq} ${uidText} 签到失败: ${r.result.message}`)
      })
    }

    // 按游戏分类统计结果
    const gameStats = {
      gs: { success: 0, failed: 0, results: [] },
      sr: { success: 0, failed: 0, results: [] }
    }

    gameStats[game].success = successCount
    gameStats[game].failed = failedCount
    gameStats[game].results = results

    return {
      total: users.length,
      success: successCount,
      failed: failedCount,
      results,
      gameStats,
      game,
      gameName
    }
  }

  /**
   * 自动签到任务（所有用户，所有游戏）
   */
  async autoSignTask() {
    logger.info('[签到插件] 开始执行自动签到任务')
    
    // 获取原神和星铁的自动签到用户
    const gsUsers = this.storage.getAutoSignUsers('gs')
    const srUsers = this.storage.getAutoSignUsers('sr')
    
    const allTasks = [
      ...gsUsers.map(u => ({ ...u, game: 'gs', gameName: '原神' })),
      ...srUsers.map(u => ({ ...u, game: 'sr', gameName: '星铁' }))
    ]
    
    if (allTasks.length === 0) {
      logger.info('[签到插件] 没有需要自动签到的用户')
      return {
        total: 0,
        success: 0,
        failed: 0,
        results: []
      }
    }

    logger.info(`[签到插件] 共 ${allTasks.length} 个签到任务 (原神:${gsUsers.length}, 星铁:${srUsers.length})`)

    const results = []
    let successCount = 0
    let failedCount = 0

    for (const task of allTasks) {
      try {
        // 添加延迟，避免请求过快
        const interval = Config.get('autoSign.interval', 3) * 1000
        const randomDelay = Config.get('autoSign.randomDelay', 2) * 1000
        await this.sleep(interval + Math.random() * randomDelay)
        
        // 获取对应游戏的UID
        let uid = null
        
        if (task.game === 'gs') {
          // 原神直接使用默认UID
          uid = task.uid
        } else if (task.game === 'sr') {
          // 星铁需要单独获取UID（不能用原神的UID）
          const UserManagerClass = (await import('./UserManager.js')).default
          const userManager = new UserManagerClass()
          // 先尝试从本地获取星铁UID
          const srUid = await userManager.getGameUid(task.qq, 'sr')
          if (srUid) {
            uid = srUid
            logger.info(`[签到插件] 从本地获取星铁UID: ${uid}`)
          } else {
            // 本地没有，从API获取
            logger.info(`[签到插件] 本地未找到星铁UID，尝试从API获取`)
            uid = await userManager.getGameUidFromApi(task.qq, task.cookie, 'sr')
            if (uid) {
              logger.info(`[签到插件] 从API获取到星铁UID: ${uid}`)
            }
          }
        }
        
        if (!uid) {
          logger.warn(`[签到插件] QQ:${task.qq} ${task.gameName} 未找到UID，跳过`)
          failedCount++
          results.push({
            qq: task.qq,
            game: task.game,
            result: { success: false, message: '未找到UID' }
          })
          continue
        }
        
        const result = await this.sign(task.qq, uid, task.cookie, task.game)
        
        if (result.success) {
          successCount++
        } else {
          failedCount++
        }

        results.push({
          qq: task.qq,
          uid: uid,
          game: task.game,
          gameName: task.gameName,
          result
        })

      } catch (error) {
        logger.error(`[签到插件] QQ:${task.qq} ${task.gameName} 自动签到异常:`, error)
        failedCount++
        results.push({
          qq: task.qq,
          game: task.game,
          uid: task.uid,
          result: {
            success: false,
            message: error.message
          }
        })
      }
    }

    logger.info(`[签到插件] 自动签到任务完成: 成功${successCount}个, 失败${failedCount}个`)

    // 按游戏分类统计结果
    const gameStats = {
      gs: { success: 0, failed: 0, results: [] },
      sr: { success: 0, failed: 0, results: [] }
    }

    for (const result of results) {
      const game = result.game || 'gs'
      if (!gameStats[game]) continue
      
      if (result.result?.success) {
        gameStats[game].success++
      } else {
        gameStats[game].failed++
      }
      gameStats[game].results.push(result)
    }

    return {
      total: allTasks.length,
      success: successCount,
      failed: failedCount,
      results,
      gameStats  // 按游戏分类的统计
    }
  }

  /**
   * 延迟函数
   */
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
  }

  /**
   * 获取失败原因汇总
   * @param {Array} results - 签到结果列表
   * @returns {Array} 去重后的失败原因列表
   */
  getFailedReasons(results) {
    const failedResults = results.filter(r => !r.result.success)
    const reasons = failedResults.map(r => r.result.message)
    // 去重
    return [...new Set(reasons)]
  }

  /**
   * 格式化签到结果消息
   */
  formatSignResult(result, gameName = '原神') {
    if (!result.success) {
      return `【${gameName}】签到失败\n${result.message}`
    }

    let msg = ''
    
    if (result.alreadySigned) {
      msg = `【${gameName}】${result.message}\n`
    } else {
      msg = `【${gameName}】签到成功！\n`
    }
    
    // 显示奖励信息（签到成功和已签到都显示）
    if (result.reward) {
      msg += `今日奖励：${result.reward.name} x${result.reward.count}\n`
    }
    
    // 显示签到统计
    if (result.data) {
      msg += `本月签到：${result.data.totalSignDay}天\n`
      msg += `本月漏签：${result.data.missedDays}次`
    }

    return msg
  }

  /**
   * 推送自动签到结果
   * @param {object} taskResult - 自动签到任务结果
   * @param {object} Bot - Bot实例
   */
  async pushSignResult(taskResult, Bot) {
    if (!Bot) {
      logger.warn('[签到插件] Bot实例不存在，无法推送')
      return
    }

    const pushUsers = this.storage.getPushUsers()
    const allResults = taskResult.results

    // 1. 群聊推送（按群统计）
    for (const [groupId, users] of Object.entries(pushUsers.groups)) {
      try {
        // 获取该群用户的QQ列表
        const groupUserQQs = users.map(u => u.qq)
        
        // 筛选出属于该群的用户的签到结果
        const groupResults = allResults.filter(r => groupUserQQs.includes(r.qq))
        
        if (groupResults.length === 0) continue
        
        // 按游戏分类统计
        const groupStats = {
          gs: { success: 0, failed: 0, results: [] },
          sr: { success: 0, failed: 0, results: [] }
        }
        
        for (const result of groupResults) {
          const game = result.game
          const isSuccess = result.result?.success
          
          if (game === 'gs') {
            if (isSuccess) groupStats.gs.success++
            else groupStats.gs.failed++
            groupStats.gs.results.push(result)
          } else if (game === 'sr') {
            if (isSuccess) groupStats.sr.success++
            else groupStats.sr.failed++
            groupStats.sr.results.push(result)
          }
        }
        
        const messages = []
        
        // 原神统计
        if (groupStats.gs.success + groupStats.gs.failed > 0) {
          messages.push(
            `【原神自动签到完成】`,
            `✓ 成功：${groupStats.gs.success}人`,
            `✗ 失败：${groupStats.gs.failed}人`
          )
          
          // 显示失败原因（如果有）
          if (groupStats.gs.failed > 0) {
            const failedReasons = this.getFailedReasons(groupStats.gs.results)
            if (failedReasons.length > 0) {
              messages.push(`失败原因：${failedReasons.join('、')}`)
            }
          }
        }
        
        // 星铁统计
        if (groupStats.sr.success + groupStats.sr.failed > 0) {
          if (messages.length > 0) messages.push('')
          messages.push(
            `【星铁自动签到完成】`,
            `✓ 成功：${groupStats.sr.success}人`,
            `✗ 失败：${groupStats.sr.failed}人`
          )
          
          // 显示失败原因（如果有）
          if (groupStats.sr.failed > 0) {
            const failedReasons = this.getFailedReasons(groupStats.sr.results)
            if (failedReasons.length > 0) {
              messages.push(`失败原因：${failedReasons.join('、')}`)
            }
          }
        }

        if (messages.length > 0) {
          await Bot.pickGroup(groupId).sendMsg(messages.join('\n'))
          logger.info(`[签到插件] 已推送到群聊 ${groupId}: 原神(${groupStats.gs.success}成功/${groupStats.gs.failed}失败) 星铁(${groupStats.sr.success}成功/${groupStats.sr.failed}失败)`)
        }
      } catch (error) {
        logger.error(`[签到插件] 推送到群聊 ${groupId} 失败: ${error.message}`)
      }
    }

    // 2. 私聊推送（个人结果）
    for (const user of pushUsers.private) {
      try {
        const { qq, pushConfig } = user
        const userResults = taskResult.results.filter(r => r.qq === qq)
        
        if (userResults.length === 0) continue

        const messages = []
        
        for (const result of userResults) {
          const gameName = result.gameName || (result.game === 'gs' ? '原神' : '星铁')
          const isSuccess = result.result?.success
          
          // 只推送成功消息（如果开启）
          if (isSuccess && pushConfig.privateSuccess) {
            messages.push(this.formatSignResult(result.result, gameName))
          }
          
          // 只推送失败消息（如果开启）
          if (!isSuccess && pushConfig.privateFail) {
            messages.push(this.formatSignResult(result.result, gameName))
          }
        }

        if (messages.length > 0) {
          await Bot.pickFriend(qq).sendMsg(messages.join('\n\n'))
          logger.info(`[签到插件] 已推送到私聊 ${qq}`)
        }
      } catch (error) {
        logger.error(`[签到插件] 推送到私聊 ${user.qq} 失败: ${error.message}`)
      }
    }
  }
}

